package com.yk.neon.lib.util.mybatis.handler;

import com.yk.neon.lib.util.mybatis.constant.EnumType;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EnumValueStringTypeHandler<E extends Enum<?> & EnumType<String>> extends BaseTypeHandler<E> {

	private Class<E> type;

	public EnumValueStringTypeHandler(Class<E> type) {
		this.type = type;
		E[] enums = type.getEnumConstants();
		if (enums == null) {
			throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
		}
	}

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
		ps.setString(i, parameter.value());
	}

	@Override
	public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
		String i = rs.getString(columnName);
		if (rs.wasNull()) {
			return null;
		} else {
			return getEnumInstance(type, i);
		}
	}

	@Override
	public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		String i = rs.getString(columnIndex);
		if (rs.wasNull()) {
			return null;
		} else {
			return getEnumInstance(type, i);
		}
	}

	@Override
	public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		String i = cs.getString(columnIndex);
		if (cs.wasNull()) {
			return null;
		} else {
			return getEnumInstance(type, i);
		}
	}

	private E getEnumInstance(Class<E> type, String i) {
		for (E e : type.getEnumConstants()) {
			if (e.isSame(i)) {
				return e;
			}
		}
		throw new IllegalStateException("No such value(" + i + ") in Enum " + type.getName());
	}

}
